const Router = require('koa-router')
const Cart = require('../../models/cart')
const Goods = require('../../models/goods')
const mongoose = require('mongoose')

const router = new Router()

/*
* @method GET
* @route /cart/getCart
* @param none
* @description 需要验证token  根据token的uid获取购物车信息
* */
const getCart = async ctx => {
  const { user } = ctx.state
  await Cart.aggregate([
    { $match: { uid: mongoose.Types.ObjectId(user.id) } },
    { // 关联查询  查询商品信息
      $lookup: {
        from: 'goods',
        localField: 'gid',
        foreignField: '_id',
        as: 'goods'
      }
    },
    { $unwind: '$goods' } // 经过上面查询出来 goods是一个数组 数组包裹商品数据
    // 但是指定的uid和cartId只会对应一个商品 所以这里使用unwind unwind专门用于拆解数组 具体百度
  ]).then(async res => {
    // TODO 希望可以获取库存 并且根据库存来设置该条购物车的状态 status
    console.log('获取购物车成功', res)
    ctx.status = 200
    ctx.body = res
  }).catch(err => {
    console.log('获取购物车失败', err)
    ctx.status = 500
    ctx.body = err
  })
}
router.get('/getCart', getCart)

/*
* @method POST
* @route cart/addCart
* @param  gid goods_num
* @description 需要验证token  添加购物车信息
* */
const addCart = async ctx => {
  const { user } = ctx.state
  const { body } = ctx.request
  // 找到并升级 如果没有找到会自动创建一个新的
  // https://blog.csdn.net/qq_33206732/article/details/80310371 findOneAndUpdate的文档

  // 这里应该有一个判断 如果这个物品购物车已经有了 就应该找到并且升级  如果没有就要创建新的
  await Cart.find({ uid: user.id, gid: body.gid }).then(async res => {
    // 如果找到了
    res.length
      ? await inc(ctx)
      : await new Cart({
        uid: user.id, gid: body.gid, goods_num: parseInt(body.goods_num)
      }).save().then(res => {
        console.log('创建新的购物车文档 save成功', res)
        ctx.status = 200
        ctx.body = res
      }).catch(err => {
        console.log('创建新的购物车文档  save失败', err)
        ctx.status = 500
        ctx.body = err
      })
  }).catch(err => {
    console.log('购物车find错误', err)
    ctx.status = 500
    ctx.body = err
  })
}
router.post('/addCart', addCart)

/*
* @method PUT
* @route /cart/putCart
* @param cid goods_num
* @description 需要验证token  用于修改购物车信息
* */
const putCart = async ctx => {
  const { cid, goods_num } = ctx.request.body
  const inventory = await getGoodsInventory(ctx)
  console.log(inventory, goods_num, inventory >= goods_num)
  if (inventory >= goods_num) {
    await Cart.findOneAndUpdate(
      { _id: cid },
      // 是不是用$set都可以
      { $set: { goods_num: parseInt(goods_num) } },
      { new: true }
    ).then(res => {
      console.log('购物车修改成功', res)
      ctx.status = 200
      ctx.body = res
    }).catch(err => {
      console.log('购物车修改失败', err)
      ctx.status = 500
      ctx.body = err
    })
  } else {
    ctx.status = 500
    ctx.body = { msg: '修改失败,超过库存' }
  }
}
router.put('/putCart', putCart)

/*
* @method PUT
* @route /cart/setChecked
* @param cid checked
* @description 需要验证token 用于设置购物车信息的checked字段
* */
const setChecked = async ctx => {
  try {
    const { cid, checked } = ctx.request.body
    console.log(cid, checked)
    await Cart.findOneAndUpdate(
      { _id: cid }, { $set: { checked } }
    ).then(res => {
      console.log('setChecked成功 ', res)
      ctx.status = 200
      ctx.body = res
    })
  } catch (e) {
    console.log('setChecked报错', e)
    ctx.status = 500
    ctx.body = e
  }
}
router.put('/setChecked', setChecked)

/*
* @method DELETE
* @route /cart/deleteCart
* @param cid
* @description 需要验证token  用于删除购物车信息 有一条和多条删除
* */
const deleteCart = async ctx => {
  // 在node中前端向后端发送数组的话 非常简单 像get,delete这种请求就直接接收就是了  比如发送的cid:[]  后端直接ctx.query['cid[]']
  const cid = ctx.query['cid[]']
  // 注意 这里使用deleteMany()与remove()是一样的  remove()是deleteMany的别名
  await Cart.deleteMany({
    // 重点是这里 这里的匹配规则 $in  匹配_id字段所有的cid数组里面的所有元素
    _id: { $in: cid }
  }).then(res => {
    console.log(res, 'res')
    ctx.status = 200
    ctx.body = res
  }).catch(err => {
    console.log(err, 'err')
    ctx.status = 500
    ctx.body = err
  })
}
router.delete('/deleteCart', deleteCart)

const inc = async (ctx) => {
  const { user } = ctx.state
  const { body } = ctx.request
  try {
    const inventory = await getGoodsInventory(ctx)
    // 注意哦 这里的findOne返回的是一个Query类型的 根据mongoose的Query类型准则可以继续进行操作
    const findCart = await Cart.findOne({ uid: user.id, gid: body.gid })
    const res = Number(findCart.goods_num) + Number(body.goods_num)
    if (res >= 0 && res <= inventory) {
      await findCart.update({ $set: { goods_num: res } }).then(res => {
        console.log('inc成功 res', res)
        ctx.status = 200
        ctx.body = res
      })
    } else {
      ctx.status = 500
      ctx.body = { msg: 'inc修改失败,库存不允许' }
    }
  } catch (e) {
    console.log('inc函数报错了', e)
  }
}
const getGoodsInventory = async (ctx, defaultGid) => {
  const gid = defaultGid || ctx.query.gid || ctx.request.body.gid
  return await Goods.findById(mongoose.Types.ObjectId(gid)).then(res => {
    if (res) return res.inventory
    else return false
  }).catch(err => {console.log('返回商品库存报错', err)})
}

module.exports = router.routes()
